/**
 * Set：一种不允许值重复的顺序数据结构
 * 
 * add(element)：向集合添加一个新元素。
 * delete(element)：从集合移除一个元素。
 * has(element)：如果元素在集合中，返回 true，否则返回 false。
 * clear()：移除集合中的所有元素。
 * size()：返回集合所包含元素的数量。它与数组的 length 属性类似。
 * values()：返回一个包含集合中所有值（元素）的数组。
 * 
 * @class Set
 */
class Set {
  constructor(){
    this.items = {};
  }

  has(element){
    return Object.prototype.hasOwnProperty.call(this.items, element);
  }
  
  add(element){
    if(!this.has(element)){
      this.items[element] = element;
      return true;
    }
    return false;
  }

  delete(element){
    if(this.has(element)){
      delete this.items[element];
      return true;
    }
    return false;
  }

  clear(){
    this.items = {};
  }

  size(){
    let count = 0;
    for(let key in this.items){
      if(this.items.hasOwnProperty(key)){
        count++;
      }
    }
    return count;
    // return Object.keys(this.items).length;
  }

  values(){
    let values = [];
    for(let key in this.items){
      if(this.items.hasOwnProperty(key)){
        values.push(key);
      }
    }
    return values;
    // return  Object.values(this.items);
  }

  // 并集 思路：Set数据结构是不存在重复的数据的，可以把两个集合放在同一个Set
  union(otherSet){
    const unionSet = new Set();
    this.values().forEach(value => unionSet.add(value));
    otherSet.values().forEach(value => unionSet.add(value));
    return unionSet;
  }

  // 交集 思路：以集合A为基础，拿集合B的值去集合A理匹配，存在就添加到集合C，集合C就是集合A和B的交集
  intersection(otherSet) { 
    const intersectionSet = new Set();
    const values = this.values(); 
    for (let i = 0; i < values.length; i++) {
      if (otherSet.has(values[i])) { 
        intersectionSet.add(values[i]);
      } 
    } 
    return intersectionSet; 
  }

  // 差集 思路：以集合A为基础，拿集合B的值去集合A理匹配，不存在就添加到集合C，集合C就是集合A和B的差集
  difference(otherSet) { 
    const differenceSet = new Set();
    this.values().forEach(value => {
      if (!otherSet.has(value)) {
        differenceSet.add(value);
      } 
    }); 
    return differenceSet; 
   }
}

// 测试代码
const set = new Set(); 
set.add(1); 
console.log(set.values()); // 输出[1] 
console.log(set.has(1)); // 输出 true 
console.log(set.size()); // 输出 1 
set.add(2); 
console.log(set.values()); // 输出[1, 2] 
console.log(set.has(2)); // 输出 true 
console.log(set.size()); // 输出 2 
set.delete(1); 
console.log(set.values()); // 输出[2] 
set.delete(2); 
console.log(set.values()); // 输出[]



const setA = new Set(); 
setA.add(1); 
setA.add(2); 
setA.add(3); 
const setB = new Set(); 
setB.add(3); 
setB.add(4); 
setB.add(5); 
setB.add(6); 
// 测试并集
const unionAB = setA.union(setB); 
console.log(unionAB.values());
// 测试交集
const intersectionAB = setA.intersection(setB); 
console.log(intersectionAB.values());
// 测试差集
const differenceAB = setA.difference(setB); 
console.log(differenceAB.values());



// es6
let arr1 = [1,2,3];
let arr2 = [2,3,4];
let set1 = new Set(arr1);
let set2 = new Set(arr2);
//求并集
let union = new Set([...set1,...set2]);
console.log('并集',union);
//求交集
let intersect = new Set([...set1].filter(x => set2.has(x)));
console.log('交集',intersect);
//求差集
let diffrence = new Set([...set1].filter(x => !set2.has(x)));
console.log('差集',diffrence);